package com.corpgovernment.common.logging.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.apache.commons.collections4.MapUtils;
import org.slf4j.MDC;

import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.logging.bo.LogTagConstants;
import com.corpgovernment.common.logging.bo.LogTags;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.utils.StringUtils;

/**
 *  @author: pwang27
 *  @Date: 2023/11/9 20:16
 *  @Description: 日志工具类
 */
public class LoggerUtils {

    public static Map<String, String> getTags() {
        return MDC.getCopyOfContextMap();
    }

    /**
     * 设置公共标签
     *
     * @param tagsMap 公共标签集合。
     */
    public static void initTags(Map<String, String> tagsMap) {
        LoggerUtils.clearTags();
        if (MapUtils.isNotEmpty(tagsMap)) {
            tagsMap.forEach(LoggerUtils::withTag);
        }
    }

    /**
     * 设置公共标签
     *
     * @param tags 公共标签集合，每2个为一组，不足2个忽略。
     */
    public static void initTags(String... tags) {
        LoggerUtils.clearTags();
        if (Objects.isNull(tags)) {
            return;
        }

        for (int i = 0; i + 1 < tags.length; i += 2) {
            LoggerUtils.withTag(tags[i], tags[i + 1]);
        }
    }

    /**
     * 设置公共标签
     *
     * @param tags 公共标签类
     */
    public static void initTags(LogTags tags) {
        LoggerUtils.clearTags();
        if (Objects.isNull(tags)) {
            return;
        }

        if (Objects.nonNull(tags.getOrderId())) {
            withTag(LogTagConstants.ORDER_ID, tags.getOrderId());
        }

        if (Objects.nonNull(tags.getSupplierOrderId())) {
            withTag(LogTagConstants.SUPPLIER_ORDER_ID, tags.getSupplierOrderId());
        }

        BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);
        addTag(LogTagConstants.UID, tags.getUid(),
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getUid).orElse(null));
        addTag(LogTagConstants.CORP_ID, tags.getCorpId(),
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getCorpId).orElse(null));
        addTag(LogTagConstants.SUPPLIER_CODE, tags.getSupplierCode(),
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getSupplierCode).orElse(null));

        if (tags.getParameters() != null) {
            tags.getParameters().forEach(LoggerUtils::withTag);
        }
    }

    /**
     * 设置公共标签
     *
     */
    public static void initTags() {
        LoggerUtils.clearTags();
        BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);
        addTag(LogTagConstants.UID, null,
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getUid).orElse(null));
        addTag(LogTagConstants.CORP_ID, null,
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getCorpId).orElse(null));
        addTag(LogTagConstants.SUPPLIER_CODE, null,
                Optional.ofNullable(baseUserInfo).map(BaseUserInfo::getSupplierCode).orElse(null));
    }

    /**
     * 基础的数据设置
     *
     * @param tag
     * @param tagData
     * @param baseTagData
     */
    private static void addTag(String tag, String tagData, String baseTagData) {
        if (StringUtils.isNotBlank(tagData)) {
            withTag(tag, tagData);
            return;
        }

        if (StringUtils.isBlank(baseTagData)) {
            return;
        }
        withTag(tag, baseTagData);
    }

    /**
     * 新增tag
     * @param key
     * @param value
     * @return
     */
    public static void withTag(String key, Object value) {
        if (StringUtils.isBlank(key) || Objects.isNull(value)) {
            return;
        }
        MDC.put(key.toLowerCase(), String.valueOf(value));
    }

    /**
     * 删除tag
     * @param key
     * @return
     */
    public static void removeTags(String key) {
        MDC.remove(key);
    }

    /**
     * 清除tag
     * @return
     */
    public static void clearTags() {
        MDC.setContextMap(new HashMap<>());
    }

}
